使用 Terraform 的 .tfvars
文件(通常是 .tfvars 或 .auto.tfvars)有幾個好處:
.tfvars
文件,你可以將變數值從 Terraform 代碼中分離出來。這使得代碼更容易閱讀、維護和共享,並且允許不同的環境使用相同的代碼但具有不同的變數值。.tfvars
文件,你可以根據不同的需求自定義配置。這使得配置變得參數化,可以輕鬆應對不同的情境,如開發、測試和生產。.tfvars
文件可以加密或保護,以防止未授權的訪問。這有助於保護敏感資訊,如密碼、金鑰等。.tfvars
文件與團隊中的其他成員共享,並協作編輯。這有助於確保配置的一致性。.tfvars
文件,你可以在不同環境中使用相同的 Terraform 代碼。.tfvars
文件,這使得自動化和 CI/CD 流程更容易管理。.tfvars
文件,你可以避免在 Terraform 代碼中硬編碼變數值,這樣如果需要更改變數值,你只需編輯 .tfvars
文件而不必修改代碼。以下我會使用稍早的的代碼來介紹使用 .tfvars
文件的方式,要再新增三個檔案 variables.tf
、tokyo.tfvars
和osaka.tfvars
,文件結構如下:
├── main.tf
├── modules
│ └── ec2_instances
│ ├── data.aws_ami.ami.tf
│ ├── main.tf
│ ├── provider.tf
│ └── variables.tf
├── osaka.tfvars
├── provider.tf
├── tokyo.tfvars
└── variables.tf
variables.tf
: 來定義哪些變數可以動態變數方式傳入,例如:aws_region
、aws_profile
、instance_count
、instance_type
和environment
。ariable "aws_region" {
type = string
description = "AWS Region"
}
variable "aws_profile" {
type = string
description = "Profile in .aws/config"
}
variable "instance_count" {
type = number
description = "Number of EC2 instances to create"
}
variable "instance_type" {
type = string
description = "The type of EC2 instance"
}
variable "ami_id" {
type = string
description = "The ID of the AMI"
default = null
}
variable "environment" {
type = string
description = "The environment of EC2 instance"
}
tokyo.tfvars
:定義需要佈署在 Tokyo
region 資源的變數內容。aws_region = "ap-northeast-1"
aws_profile = "<YOUR_PROFILE>"
instance_count = 1
instance_type = "t3a.micro"
environment = "Osaka"
osaka.tfvars
:定義需要佈署在 Osaka
region 資源的變數內容。aws_region = "ap-northeast-3"
aws_profile = "<YOUR_PROFILE>"
instance_count = 2
instance_type = "t3a.small"
environment = "Osaka"
接下來,我們來試著用不同 .tfvars
來執行計畫看看輸出結果。
terraform plan --out .plan -var-file=tokyo.tfvars
帶入 tokyo.tfvars
變數檔案後輸出結果如下:module.my_ec2_instances.data.aws_ami.selected_ami: Reading...
module.my_ec2_instances.data.aws_ami.selected_ami: Read complete after 0s [id=ami-0f419d2f905bb344e]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.my_ec2_instances.aws_instance.example[0] will be created
+ resource "aws_instance" "example" {
+ ami = "ami-0f419d2f905bb344e"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_lifecycle = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t3a.micro"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ spot_instance_request_id = (known after apply)
+ subnet_id = (known after apply)
+ tags = {
+ "Environment" = "Dev"
+ "Name" = "ec2-instance-0"
}
+ tags_all = {
+ "Environment" = "Dev"
+ "Name" = "ec2-instance-0"
}
+ tenancy = (known after apply)
+ user_data = (known after apply)
+ user_data_base64 = (known after apply)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
───────────────────────────────────────────────────────────────────────
Saved the plan to: .plan
To perform exactly these actions, run the following command to apply:
terraform apply ".plan"
terraform plan --out .plan -var-file=osaka.tfvars
帶入 osaka.tfvars
變數檔案後輸出結果如下:module.my_ec2_instances.data.aws_ami.selected_ami: Reading...
module.my_ec2_instances.data.aws_ami.selected_ami: Read complete after 1s [id=ami-035f22189112edf2e]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# module.my_ec2_instances.aws_instance.example[0] will be created
+ resource "aws_instance" "example" {
+ ami = "ami-035f22189112edf2e"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_lifecycle = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t3a.micro"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ spot_instance_request_id = (known after apply)
+ subnet_id = (known after apply)
+ tags = {
+ "Environment" = "Dev"
+ "Name" = "ec2-instance-0"
}
+ tags_all = {
+ "Environment" = "Dev"
+ "Name" = "ec2-instance-0"
}
+ tenancy = (known after apply)
+ user_data = (known after apply)
+ user_data_base64 = (known after apply)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (known after apply)
}
# module.my_ec2_instances.aws_instance.example[1] will be created
+ resource "aws_instance" "example" {
+ ami = "ami-035f22189112edf2e"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_lifecycle = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t3a.micro"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ spot_instance_request_id = (known after apply)
+ subnet_id = (known after apply)
+ tags = {
+ "Environment" = "Dev"
+ "Name" = "ec2-instance-1"
}
+ tags_all = {
+ "Environment" = "Dev"
+ "Name" = "ec2-instance-1"
}
+ tenancy = (known after apply)
+ user_data = (known after apply)
+ user_data_base64 = (known after apply)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (known after apply)
}
Plan: 2 to add, 0 to change, 0 to destroy.
───────────────────────────────────────────────────────────────────────
Saved the plan to: .plan
To perform exactly these actions, run the following command to apply:
terraform apply ".plan"
從上述執行計畫結果,它會以不同 .tfvars
內給定的變數內容來決定佈署到不同環境,且使用同一份模組代碼可以動態決定佈署的資源項目非常的方便。
你可以使用 git-secret
工具幫助你安全地加密 Terraform 的 .tfvars
文件,以防止未經授權的訪問,步驟如下:
git-secret
: 在你的 Git repository 中,首先初始化 git-secret
,在 repository 當前目錄中運行以下命令:git secret init
.gitignore
文件: 將 .tfvars
文件不要新增到 Git repository 中。echo "*..tfvars" > .gitignore
git secret add
命令將文件加密與 git secret hide -m
將檔案進行加密儲存。git secret add tokyo.tfvars
git secret add osaka.tfvars
git secret hide -m
git add
和 git commit
命令確認變更。git add .gitignore
git add *.secret
git commit -m "Add encrypted .tfvars file"
git push
下一天,將說明如何實作多個模組間相依性。